package org.example.domain.strategy.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import org.example.domain.strategy.model.Raffle.RaffleAwardEntity;
import org.example.domain.strategy.model.Raffle.RaffleFactorEntity;
import org.example.domain.strategy.model.Raffle.StrategyAwardEntity;
import org.example.domain.strategy.repository.IStrategyRepository;
import org.example.domain.strategy.service.rule.Chain.factory.DefaultLogicChainFactory;
import org.example.domain.strategy.service.armory.IStrategyDispatch;
import org.example.domain.strategy.service.rule.Tree.Engine.factory.DefaultTreeFactory;
import org.example.types.enums.ResponseCode;
import org.example.types.exception.AppException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

//抽奖规则分为总体策略过滤规则和奖品策略过滤规则,
//总体策略规则存放了一个策略所包含的总体过滤规则,在strategy的rule_models表里面,
//奖品过滤规则存放了一个奖品所包含的奖品过滤规则,在strategy_award的rule_models里面
//他们的规则过滤的值都存放在一个表strategy_rule里面


//模板策略模式,通过在抽象类中的非抽象方法中调用抽象方法,并定义业务总体执行流程,抽象方法用来给子类实现,以做到共用同一套流程,但实现细节如抽象方法的实现不一样
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy,IRaffleStock ,IRaffleRule{

    @Autowired
    private IStrategyRepository strategyRepository;

    @Autowired
    private IStrategyDispatch strategyDispatch;

    @Autowired
    DefaultLogicChainFactory defaultLogicChainFactory;

    @Autowired
    private DefaultTreeFactory defaultTreeFactory;



    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
        // 1. 参数校验
        //获取抽奖因子,用户名和策略id
        Long strategyId = raffleFactorEntity.getStrategyId();
        String userId = raffleFactorEntity.getUserId();
        if (strategyId == null || StringUtils.isBlank(userId))
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());

        //1.执行抽奖前规则,采用责任链式
        DefaultLogicChainFactory.StrategyAwardVO chainStrategyAwardVO = raffleLogicChain(strategyId, userId);
        log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getRuleModel());
        if (!DefaultLogicChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVO.getRuleModel())) {
            return buildRaffleAwardEntity(strategyId,chainStrategyAwardVO.getAwardId(),chainStrategyAwardVO.getAwardRuleValue());
        }

        //2.执行抽奖中规则,采用组合模式,树状
        DefaultTreeFactory.StrategyAwardVO treeStrategyAwardVO = raffleLogicTree(strategyId, chainStrategyAwardVO.getAwardId(), userId,raffleFactorEntity.getEndDateTime());
        log.info("抽奖策略计算-规则树 {} {} {} {}", userId, strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());

        return buildRaffleAwardEntity(strategyId,treeStrategyAwardVO.getAwardId(),treeStrategyAwardVO.getAwardRuleValue());
    }



    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId, Integer awardId, String awardConfig) {
        StrategyAwardEntity strategyAward = strategyRepository.queryStrategyAwardEntity(strategyId, awardId);
        return RaffleAwardEntity.builder()
                .awardId(awardId)
                .strategyId(strategyId)
                .awardTitle(strategyAward.getAwardTitle())
                .awardConfig(awardConfig)
                .sort(strategyAward.getSort())
                .build();
    }



    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(Long strategyId, Integer awardId, String userId);

    public abstract DefaultLogicChainFactory.StrategyAwardVO raffleLogicChain(Long strategyId, String userId);

    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(Long strategyId, Integer awardId, String userId, Date endDateTime) ;


}
